<?php

namespace app\http\controller\admin;

use mon\util\File;
use mon\env\Config;
use mon\util\UploadFile;
use app\model\MenuModel;
use app\model\AdminModel;
use app\model\AssetsModel;
use app\model\ChatAppModel;
use app\model\ChatStayModel;
use app\model\ChatWaiterModel;
use mon\orm\exception\DbException;
use mon\util\exception\UploadException;
use app\model\ChatMessageRelationModel;

/**
 * 控制台
 */
class ConsoleController extends Controller
{
    /**
     * 框架页面
     *
     * @return string
     */
    public function index()
    {
        $data = $this->getSidebar(Config::instance()->get('admin.multiplenav', false));
        if ($this->request->isAjax()) {
            return $this->success('ok', $data);
        }
        return $this->fetch('console', $data);
    }

    /**
     * 框架桌面
     *
     * @return string
     */
    public function desktop()
    {
        // 验证过期天数
        $showDeadlineTips = false;
        if ($this->userInfo['deadline']) {
            $deadlineTips = Config::instance()->get('admin.deadline_tips', 3);
            $tipsTime = strtotime(date('Y-m-d')) + (86400 * $deadlineTips);
            if ($tipsTime >= $this->userInfo['deadline']) {
                $showDeadlineTips = true;
            }
        }

        $lineData = json_encode($this->statisData(), JSON_UNESCAPED_UNICODE);
        return $this->fetch('desktop', [
            'appCount'      => ChatAppModel::instance()->count(),
            'waiterCount'   => ChatWaiterModel::instance()->count(),
            'msgCount'      => ChatMessageRelationModel::instance()->count(),
            'stayCount'     => ChatStayModel::instance()->count(),
            'showDeadline'  => $showDeadlineTips,
            'lineData'      => $lineData
        ]);
    }

    /**
     * 获取统计数据
     *
     * @return array
     */
    protected function statisData()
    {
        $limit = 14;
        $now = strtotime(date('Y-m-d'));
        $result = [];
        for ($i = 0; $i < $limit; $i++) {
            $d = $i + 1;
            $time = $now - (86400 * $d);
            $day = date('Y-m-d', $time);
            $stay_sql = "SELECT COUNT(id) as count, '{$day}' AS date, '留言数' AS type FROM chat_stay WHERE create_time <= {$time}";
            $relation_sql = "SELECT COUNT(id) as count, '{$day}' AS date, '接待数' AS type FROM chat_message_relation WHERE create_time <= {$time}";
            $result[] =  $stay_sql;
            $result[] =  $relation_sql;
        }
        $sql = implode(' UNION ', $result);
        $data = ChatStayModel::instance()->query($sql);
        return $data;
    }

    /**
     * 修改用户信息
     *
     * @param AdminModel $model
     * @return string
     */
    public function editUserInfo(AdminModel $model)
    {
        if ($this->request->isPost()) {
            $option = $this->request->post();
            $option['idx'] = $this->userInfo['id'];
            $save = $model->reset_password($option, true);
            if (!$save) {
                return $this->error($model->getError());
            }

            return $this->success('操作成功');
        }
        return $this->fetch('userInfo');
    }

    /**
     * 文件上传
     *
     * @return string
     */
    public function upload(UploadFile $sdk)
    {
        $config = Config::instance()->get('app.upload', []);
        $rootPath = $config['root'];
        $savePath = $config['save'];
        $date = date('Ym');
        $saveDir = $rootPath . DIRECTORY_SEPARATOR . $savePath . DIRECTORY_SEPARATOR . $date . DIRECTORY_SEPARATOR;
        if (!is_dir($saveDir)) {
            $createDir = File::instance()->createDir($saveDir);
            if (!$createDir) {
                return $this->error('创建存储目录失败，请检查写入权限：' . $saveDir);
            }
        }
        $sdk->rootPath = $saveDir;
        $sdk->maxSize = $config['maxSize'];
        $sdk->exts = $config['exts'];
        try {
            $upload = $sdk->upload()->save()->getFile();
            $path = '/' . $savePath . '/' . $date . '/' . $upload['saveName'];

            // 判断是否保存的资源管理中
            $saveAssets = $this->request->post('saveAssets', false);
            if ($saveAssets) {
                $assets = AssetsModel::instance()->add([
                    'title'     => $upload['saveName'],
                    'url'       => $path,
                    'storage'   => 1,
                    'status'    => 1
                ]);
            }

            return $this->success('ok', ['url' => $path]);
        } catch (UploadException $e) {
            return $this->error($e->getMessage());
        } catch (DbException $e) {
            // 数据库保证到资源管理失败则不做处理，返回URL
            return $this->success('ok', ['url' => $path]);
        }
    }

    /**
     * 获取七牛云上传配置
     *
     * @return string
     */
    // public function qiniu()
    // {
    //     $config = Config::instance()->get('upload.qiniu', []);
    //     if (empty($config) || !$config['enable']) {
    //         return $this->error('未启用七牛云上传');
    //     }
    //     $accessKey = $config['access'];
    //     $secretKey = $config['secret'];
    //     $auth = new Auth($accessKey, $secretKey);
    //     $bucket = $config['bucket'];
    //     $expires = $config['expires'];
    //     $domain = $config['domain'];
    //     // 设置json返回格式
    //     $returnBody = '{"key":"$(key)","hash":"$(etag)","code":"1","msg":"ok","data":{"url": "' . $domain . '/$(key)"}}';
    //     $policy = array(
    //         'returnBody' => $returnBody
    //     );

    //     // 生成上传Token
    //     $token = $auth->uploadToken($bucket, null, $expires, $policy, true);
    //     return $this->success('ok', [
    //         'token' => $token
    //     ]);
    // }

    /**
     * 获取左侧菜单栏
     *
     * @param boolean $multiple 是否开启二级菜单
     * @param string $fixedPage 默认页面
     * @return string
     */
    private function getSidebar($multiple = false, $fixedPage = null)
    {
        $fixedPage = empty($fixedPage) ? Config::instance()->get('admin.admin_fixed_page', '/admin/console/desktop') : $fixedPage;
        // 获取当前用户拥有的权限节点
        $userRule = $this->auth->getAuthList($this->userInfo['id']);
        $select_id = 0;
        $selected = [];
        $ruleList = MenuModel::instance()->where('status', 1)->order('sort', 'desc')->field('id, pid, icon, name, title')->select();
        // 过滤没有权限的菜单
        foreach ($ruleList as $k => &$v) {
            // 具有权限或为第三方地址或为默认页面，则渲染
            if ($v['name'] != $fixedPage && !in_array(Config::instance()->get('rbac.admin_mark', '*'), $userRule) && !in_array(strtolower($v['name']), $userRule) && strpos($v['name'], '://') === false) {
                unset($ruleList[$k]);
                continue;
            }
            $select_id = $v['name'] == $fixedPage ? $v['id'] : $select_id;
            $selected = $v['name'] == $fixedPage ? $v : $selected;
            $v['url'] = $this->container->url->build($v['name']);
        }

        $menu = '';
        $nav = '';
        // 构造菜单数据
        if ($multiple) {
            $topList = [];
            foreach ($ruleList as $index => $item) {
                if (!$item['pid']) {
                    $topList[] = $item;
                }
            }
            $selectParentIds = [];
            if ($select_id) {
                $selectParentIds = $this->container->tree->data($ruleList)->getParentsIds($select_id, true);
            }
            foreach ($topList as $index => $item) {
                $childList = $this->getTreeMenu($ruleList, $item['id'], '<li class="@class" pid="@pid"><a href="@url" @addtabs @target url="@url"><i class="@icon"></i> <span>@title</span> <span class="pull-right-container">@caret</span> </a> @childlist</li>', $select_id, '', 'ul', 'class="treeview-menu"');
                $current = in_array($item['id'], $selectParentIds);
                $url = $childList ? 'javascript:;' : $item['url'];
                $isTarget = (strpos($url, '://') !== false);
                $addtabsTarget = !$isTarget ? 'addtabs="' . $item['id'] . '"' : 'target="_block"';
                $addtabs = ($childList || !$url || $isTarget) ? "" : (stripos($url, "?") !== false ? "&" : "?") . "ref=addtabs";
                $childList = str_replace('" pid="' . $item['id'] . '"', ' treeview ' . ($current ? '' : 'hidden') . '" pid="' . $item['id'] . '"', $childList);
                $nav .= '<li class="' . ($current ? 'active' : '') . '"><a href="' . $url . $addtabs . '" ' . $addtabsTarget . ' url="' . $url . '"><i class="' . $item['icon'] . '"></i> <span>' . $item['title'] . '</span> </a> </li>';
                $menu .= $childList;
            }
        } else {
            $menu = $this->getTreeMenu($ruleList, 0, '<li class="@class"><a href="@url" @target @addtabs url="@url"><i class="@icon"></i> <span>@title</span> <span class="pull-right-container">@caret</span> </a> @childlist</li>', $select_id, '', 'ul', 'class="treeview-menu"');
            if ($selected) {
                $nav .= '<li role="presentation" id="tab_' . $selected['id'] . '" class="active"><a href="#con_' . $selected['id'] . '" node-id="' . $selected['id'] . '" aria-controls="' . $selected['id'] . '" role="tab" data-toggle="tab"><i class="' . $selected['icon'] . ' fa-fw"></i> <span>' . $selected['title'] . '</span> </a></li>';
            }
        }

        return [
            'sideBar'   => $menu,
            'nav'       => $nav,
            'fixedmenu' => $selected
        ];
    }

    /**
     * 编译生成菜单数据
     *
     * @return string
     */
    private function getTreeMenu($ruleList, $myid, $itemtpl, $selectedids = '', $disabledids = '', $wraptag = 'ul', $wrapattr = '', $deeplevel = 0)
    {
        $str = '';
        $childs = $this->container->tree->data($ruleList)->getChild($myid);
        if ($childs) {
            foreach ($childs as $value) {
                $id = $value['id'];
                unset($value['child']);
                $selected = in_array($id, (is_array($selectedids) ? $selectedids : explode(',', $selectedids))) ? 'selected' : '';
                $disabled = in_array($id, (is_array($disabledids) ? $disabledids : explode(',', $disabledids))) ? 'disabled' : '';
                $value = array_merge($value, array('selected' => $selected, 'disabled' => $disabled));
                $value = array_combine(array_map(function ($k) {
                    return '@' . $k;
                }, array_keys($value)), $value);
                $bakvalue = array_intersect_key($value, array_flip(['@url', '@class']));
                $value = array_diff_key($value, $bakvalue);
                $nstr = strtr($itemtpl, $value);
                $value = array_merge($value, $bakvalue);
                $childdata = $this->getTreeMenu($ruleList, $id, $itemtpl, $selectedids, $disabledids, $wraptag, $wrapattr, $deeplevel + 1);
                $childlist = $childdata ? "<{$wraptag} {$wrapattr}>" . $childdata . "</{$wraptag}>" : "";
                $childlist = strtr($childlist, array('@class' => $childdata ? 'last' : ''));
                $isTarget = (isset($value['@url']) && strpos($value['@url'], '://') !== false);
                $value = array(
                    '@childlist' => $childlist,
                    '@url'       => $childdata || !isset($value['@url']) ? "javascript:;" : $value['@url'],
                    '@class'     => ($selected ? ' active' : '') . ($disabled ? ' disabled' : '') . ($childdata ? ' treeview' : ''),
                    '@target'    => $isTarget ? 'target="_block"' : '',
                    '@addtabs'   => !$isTarget ? 'addtabs="' . $value['@id'] . '"' : '',
                    '@caret'     => ($childdata) ? '<i class="fa fa-angle-left"></i>' : '',
                );
                $str .= strtr($nstr, $value);
            }
        }
        return $str;
    }
}
